home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Games / DroneZone / DZInput.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  15.3 KB  |  575 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        DZInput.c
  3.  
  4.     Contains:    xxx put contents here xxx
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     File Ownership:
  11.  
  12.         DRI:                xxx put dri here xxx
  13.  
  14.         Other Contact:        xxx put other contact here xxx
  15.  
  16.         Technology:            xxx put technology here xxx
  17.  
  18.     Writers:
  19.  
  20.         (BWS)    Brent Schorsch
  21.         (sjb)    Steve Bollinger
  22.  
  23.     Change History (most recent first):
  24.  
  25.       <SP15>    10/20/98    BWS        Pause and Quit are now separate needs
  26.         <14>     6/18/98    sjb        InputSprocket.h comes from <> place
  27. */
  28.  
  29. /*
  30.  *    File:        DZInput.c
  31.  *
  32.  *    Contents:    Handles input devices.
  33.  *
  34.  *    Copyright © 1996 Apple Computer, Inc.
  35.  */
  36.  
  37. #include <TextUtils.h>
  38.  
  39. #define USE_OLD_INPUT_SPROCKET_LABELS 0
  40. #define USE_OLD_ISPNEED_STRUCT 0
  41. #include <InputSprocket.h>
  42.  
  43. #include "DZGame.h"
  44. #include "DZInput.h"
  45. #include "DZResource.h"
  46.  
  47. #define USE_MOUSE_AND_KEYBOARD 1
  48.  
  49. #define        ISpSymmetricAxisToFloat(axis)    ((((float) axis) - kISpAxisMiddle) / (kISpAxisMaximum-kISpAxisMiddle))
  50. #define        ISpAsymmetricAxisToFloat(axis)    (((float) axis) / (kISpAxisMaximum))
  51.  
  52. /*
  53. enum {
  54.     kElement_Fire,
  55.     kElement_Pause,
  56.     kElement_ShowHUD,
  57.     kElement_ShowFPS,
  58.     kElement_Turn,
  59.     kElement_COUNT
  60. };
  61. */
  62.  
  63. enum
  64. {
  65.     kNeed_Fire,
  66.     kNeed_Roll,
  67.     kNeed_Pitch,
  68.     kNeed_Throttle,
  69.     kNeed_ThrottleUp,
  70.     kNeed_ThrottleDown,
  71.     kNeed_ThrottleFull,
  72.     kNeed_ThrottleZero,
  73.     kNeed_InertialDampers,
  74.     kNeed_Yaw,
  75.     kNeed_YawLeft,
  76.     kNeed_YawCenter,
  77.     kNeed_YawRight,
  78.     kNeed_ShowHUD,
  79.     kNeed_ShowFPS,
  80.     kNeed_ShowThrottle,
  81.     kNeed_ShowVelocity,
  82.     kNeed_InstantStop,
  83.     kNeed_Pause,
  84.     kNeed_COUNT
  85. };
  86.  
  87. #define        kNeedsVersion        1
  88.  
  89. static Boolean                    gInputActive = false;
  90. static ISpElementListReference    gInputEventList = NULL;
  91. static ISpElementListReference    gInputHoldDownEventList = NULL;
  92. static ISpElementListReference    gInputYawEventList = NULL;
  93. static ISpElementListReference    gInputThrottleEventList = NULL;
  94. static ISpElementReference        gInputElement[kNeed_COUNT] = {NULL, NULL, NULL, NULL, NULL};
  95.  
  96.  
  97. /* =============================================================================
  98.  *        Input_Init (external)
  99.  *
  100.  *    Initializes the Input stuff.
  101.  * ========================================================================== */
  102. void Input_Init(
  103.     void)
  104. {
  105.     UInt32        itr;
  106.                     
  107.     ISpNeed        needs[kNeed_COUNT] =
  108.     {
  109.         { "\pFire", kIconSuiteID_Fire, 0, 0,
  110.             kISpElementKind_Button,
  111.             kISpElementLabel_Btn_Fire,
  112.             0, 0, 0, 0
  113.         },
  114.         { "\pRoll", kIconSuiteID_Roll, 0, 0,
  115.             kISpElementKind_Axis,
  116.             kISpElementLabel_Axis_Roll,
  117.             0, 0, 0, 0
  118.         },
  119.         { "\pPitch", kIconSuiteID_Pitch, 0, 0,
  120.             kISpElementKind_Axis,
  121.             kISpElementLabel_Axis_Pitch,
  122.             0, 0, 0, 0
  123.         },
  124.         { "\pThrottle", kIconSuiteID_Throttle, 0, 1,
  125.             kISpElementKind_Axis,
  126.             kISpElementLabel_Axis_Throttle,
  127.             kISpNeedFlag_Axis_AlreadyButton | kISpNeedFlag_Axis_Asymetric, 0, 0, 0
  128.         },
  129.         { "\pIncrease Throttle", kIconSuiteID_ThrottleUp, 0, 1,
  130.             kISpElementKind_Button,
  131.             kISpElementLabel_None,
  132.             kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0
  133.         },
  134.         { "\pDecrease Throttle", kIconSuiteID_ThrottleDown, 0, 1,
  135.             kISpElementKind_Button,
  136.             kISpElementLabel_None,
  137.             kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0
  138.         },
  139.         { "\pThrottle Max", kIconSuiteID_ThrottleMax, 0, 1,
  140.             kISpElementKind_Button,
  141.             kISpElementLabel_None,
  142.             kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0
  143.         },
  144.         { "\pThrottle Min", kIconSuiteID_ThrottleMin, 0, 1,
  145.             kISpElementKind_Button,
  146.             kISpElementLabel_None,
  147.             kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0
  148.         },
  149.         { "\pInertial Dampers", kIconSuiteID_InertialDampers, 0, 0,
  150.             kISpElementKind_Button,
  151.             kISpElementLabel_None,
  152.             0, 0, 0, 0
  153.         },
  154.         { "\pRudder", kIconSuiteID_Rudder, 0, 2,
  155.             kISpElementKind_Axis,
  156.             kISpElementLabel_Axis_Rudder,
  157.             kISpNeedFlag_Axis_AlreadyButton, 0, 0, 0
  158.         },
  159.         { "\pYaw Left", kIconSuiteID_RudderLeft, 0, 2,
  160.             kISpElementKind_Button,
  161.             kISpElementLabel_Btn_LookLeft,
  162.             kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0
  163.         },
  164.         { "\pYaw Center", kIconSuiteID_RudderCenter, 0, 2,
  165.             kISpElementKind_Button,
  166.             kISpElementLabel_None,
  167.             kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0
  168.         },
  169.         { "\pYaw Right", kIconSuiteID_RudderRight, 0, 2,
  170.             kISpElementKind_Button,
  171.             kISpElementLabel_Btn_LookRight,
  172.             kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0
  173.         },
  174.         { "\pShow HUD", kIconSuiteID_ShowHUD, 0, 0,
  175.             kISpElementKind_Button,
  176.             kISpElementLabel_None,
  177.             0, 0, 0, 0
  178.         },
  179.         { "\pShow FPS", kIconSuiteID_ShowFPS, 0, 0,
  180.             kISpElementKind_Button,
  181.             kISpElementLabel_None,
  182.             0, 0, 0, 0
  183.         },
  184.         { "\pShow Throttle", kIconSuiteID_ShowThrottle, 0, 0,
  185.             kISpElementKind_Button,
  186.             kISpElementLabel_None,
  187.             0, 0, 0, 0
  188.         },
  189.         { "\pShow Velocity", kIconSuiteID_ShowVelocity, 0, 0,
  190.             kISpElementKind_Button,
  191.             kISpElementLabel_None,
  192.             0, 0, 0, 0
  193.         },
  194.         { "\pInstant Stop", kIconSuiteID_InstantStop, 0, 0,
  195.             kISpElementKind_Button,
  196.             kISpElementLabel_None,
  197.             0, 0, 0, 0
  198.         },
  199.         { "\pPause", kIconSuiteID_Pause, 0, 0,
  200.             kISpElementKind_Button,
  201.             kISpElementLabel_Btn_StartPause,
  202.             0, 0, 0, 0
  203.         }
  204.     };
  205.     
  206.     // Get the names for the needs
  207.     for (itr = 0; itr < kNeed_COUNT; itr++)
  208.         GetIndString(needs[itr].name,        kStrListID_NeedsNames,    itr+1);
  209.     
  210.     #if USE_MOUSE_AND_KEYBOARD
  211.         
  212.         // Enable the mouse
  213.         ISpDevices_ActivateClass (kISpDeviceClass_Mouse);
  214.         
  215.         // Enable the keyboard
  216.         ISpDevices_ActivateClass (kISpDeviceClass_Keyboard);
  217.     #endif
  218.     
  219.     // Set our virtual elements
  220.       ISpElement_NewVirtualFromNeeds(kNeed_COUNT, needs, gInputElement, 0);
  221.     
  222.     // Autoconfigure our virtual elements based on our needs
  223.     ISpInit(kNeed_COUNT, needs, gInputElement, ' dz ', kNeedsVersion, 0, kSetListID, 0);
  224.       
  225.      // Build two lists of elements, which we'll poll for events 
  226.      // the 'hold down' list reports both up and down events
  227.     ISpElementList_New(0, NULL, &gInputEventList, 0);
  228.     ISpElementList_New(0, NULL, &gInputHoldDownEventList, 0);
  229.     
  230.     // Add the virtual elements one at a time so we can assign a refcon
  231.     ISpElementList_AddElements(gInputHoldDownEventList, kInputEvent_Fire_On,1, &gInputElement[kNeed_Fire]);
  232.  
  233.     ISpElementList_AddElements(gInputHoldDownEventList, kInputEvent_InertialDampers_On,
  234.                                                                             1, &gInputElement[kNeed_InertialDampers]);
  235.     
  236.     ISpElementList_AddElements(gInputEventList, kInputEvent_InstantStop,     1, &gInputElement[kNeed_InstantStop]);
  237.  
  238.     ISpElementList_AddElements(gInputEventList, kInputEvent_ShowHUD,         1, &gInputElement[kNeed_ShowHUD]);
  239.     ISpElementList_AddElements(gInputEventList, kInputEvent_ShowFPS,         1, &gInputElement[kNeed_ShowFPS]);
  240.     ISpElementList_AddElements(gInputEventList, kInputEvent_ShowThrottle,     1, &gInputElement[kNeed_ShowThrottle]);
  241.     ISpElementList_AddElements(gInputEventList, kInputEvent_ShowVelocity,     1, &gInputElement[kNeed_ShowVelocity]);
  242.     
  243.     ISpElementList_AddElements(gInputEventList, kInputEvent_Pause,             1, &gInputElement[kNeed_Pause]);
  244.  
  245.  
  246.       // Build our list of elements used for the rudder (yaw) when from buttons
  247.     ISpElementList_New(0, NULL, &gInputYawEventList, 0);
  248.     
  249.     // Add the virtual elements one at a time so we can assign a refcon
  250.     ISpElementList_AddElements(gInputYawEventList, kNeed_YawLeft, 1, &gInputElement[kNeed_YawLeft]);
  251.     ISpElementList_AddElements(gInputYawEventList, kNeed_YawCenter, 1, &gInputElement[kNeed_YawCenter]);
  252.     ISpElementList_AddElements(gInputYawEventList, kNeed_YawRight, 1, &gInputElement[kNeed_YawRight]);
  253.  
  254.  
  255.       // Build our list of elements used for the throttle when from buttons
  256.     ISpElementList_New(0, NULL, &gInputThrottleEventList, 0);
  257.     
  258.     // Add the virtual elements one at a time so we can assign a refcon
  259.     ISpElementList_AddElements(gInputThrottleEventList, kNeed_ThrottleUp, 1, &gInputElement[kNeed_ThrottleUp]);
  260.     ISpElementList_AddElements(gInputThrottleEventList, kNeed_ThrottleDown, 1, &gInputElement[kNeed_ThrottleDown]);
  261.     ISpElementList_AddElements(gInputThrottleEventList, kNeed_ThrottleFull, 1, &gInputElement[kNeed_ThrottleFull]);
  262.     ISpElementList_AddElements(gInputThrottleEventList, kNeed_ThrottleZero, 1, &gInputElement[kNeed_ThrottleZero]);
  263.  
  264.      // Start off suspended (because the game is stopped)
  265.     ISpSuspend();
  266. }
  267.  
  268.  
  269. /* =============================================================================
  270.  *        Input_Exit (external)
  271.  *
  272.  *    Prepares for exit.
  273.  * ========================================================================== */
  274. void Input_Exit(
  275.     void)
  276. {
  277.     if (gInputActive)
  278.     {
  279.         Input_Activate(false);
  280.     }
  281.     
  282.     if (gInputEventList != NULL)
  283.     {
  284.         ISpElementList_Dispose(gInputEventList);
  285.         gInputEventList = NULL;
  286.     }
  287.     
  288.     if (gInputHoldDownEventList != NULL)
  289.     {
  290.         ISpElementList_Dispose(gInputHoldDownEventList);
  291.         gInputHoldDownEventList = NULL;
  292.     }
  293.     
  294.      ISpStop();
  295.      
  296.     ISpElement_DisposeVirtual(kNeed_COUNT, gInputElement);
  297. }
  298.  
  299.  
  300. /* =============================================================================
  301.  *        Input_Configure (external)
  302.  *
  303.  *    Show the configuration dialog.
  304.  * ========================================================================== */
  305. void Input_Configure(
  306.     void)
  307. {
  308.      ISpConfigure(NULL);
  309. }
  310.  
  311. #if 0
  312. /* =============================================================================
  313.  *        Input_GetState (external)
  314.  *
  315.  *    This routine handles the elements that are polled.  It returns in outXTurn
  316.  *    and outYTurn the "turn" controls in the ±1 range.
  317.  * ========================================================================== */
  318. void Input_GetState(
  319.     float*                outXTurn,
  320.     float*                outYTurn)
  321. {
  322.     ISpMovementData        movementData;
  323.     double                xTurn = 0.0;
  324.     double                yTurn = 0.0;
  325.     
  326.     if (gInputActive)
  327.     {
  328.         // Get the data
  329.         ISpElement_GetComplexState(
  330.                 gInputElement[kNeed_Turn],
  331.                 sizeof(ISpMovementData),
  332.                 &movementData);
  333.         
  334.         // Turn 'em into ±1 float range
  335.         xTurn = movementData.xAxis;
  336.         xTurn -= kISpAxisMiddle;
  337.         xTurn /= kISpAxisMaximum-kISpAxisMiddle;
  338.         
  339.         yTurn = movementData.yAxis;
  340.         yTurn -= kISpAxisMiddle;
  341.         yTurn /= kISpAxisMaximum-kISpAxisMiddle;
  342.         yTurn *= -1;    // reverse axis
  343.     }
  344.     
  345.     // Return the values
  346.     *outXTurn = xTurn;
  347.     *outYTurn = yTurn;
  348. }
  349. #endif
  350.  
  351. float Input_GetRoll (void)
  352. {
  353.     ISpAxisData            axisValue = kISpAxisMiddle;
  354.     
  355.     (void) ISpElement_GetSimpleState(gInputElement[kNeed_Roll], &axisValue);
  356.     return ISpSymmetricAxisToFloat (axisValue);
  357. }
  358.  
  359. float Input_GetPitch (void)
  360. {
  361.     ISpAxisData            axisValue = kISpAxisMiddle;
  362.     
  363.     (void) ISpElement_GetSimpleState(gInputElement[kNeed_Pitch], &axisValue);
  364.     return (-1.0 * ISpSymmetricAxisToFloat (axisValue));
  365. }
  366.  
  367. float Input_GetYaw (void)
  368. {
  369.     static    float        gYawValue = 0.0;
  370.     static    Boolean        gYawInitalized = false;
  371.     
  372.     float                yawValue = gYawValue;
  373.     OSStatus            error = noErr;
  374.     ISpAxisData            axisValue;
  375.     Boolean                wasEvent;
  376.     ISpElementEvent        event;
  377.     
  378.     // should probably put the initialization check somewhere else, so does not do it every time
  379.     if (!gYawInitalized)
  380.     {
  381.         (void) ISpElement_GetSimpleState(gInputElement[kNeed_Yaw], &axisValue);
  382.         gYawValue = ISpSymmetricAxisToFloat (axisValue);
  383.  
  384.         gYawInitalized = true;
  385.     }
  386.         
  387.     // we check the axis, to see if IT was moved, if so, we use that value
  388.     wasEvent = false;
  389.     error = ISpElement_GetNextEvent (gInputElement[kNeed_Yaw], sizeof (event), &event, &wasEvent);
  390.     if (!error && wasEvent)
  391.     {
  392.         error = ISpElement_GetSimpleState(gInputElement[kNeed_Yaw], &axisValue);
  393.         if (!error) yawValue = ISpSymmetricAxisToFloat (axisValue);
  394.  
  395.         ISpElement_Flush(gInputElement[kNeed_Yaw]);
  396.     }
  397.     else do
  398.     {
  399.         error = ISpElementList_GetNextEvent (gInputYawEventList, sizeof (event), &event, &wasEvent);
  400.         
  401.         // only process valid keydown events (all the yaw events ignore button ups)
  402.         if (wasEvent && !error && (event.data == kISpButtonDown))
  403.         {
  404.             UInt32 keyFunction = event.refCon; // because we set it this way
  405.             switch (keyFunction)
  406.             {
  407.                 case kNeed_YawLeft:
  408.                     yawValue -= 0.1;
  409.                     if (yawValue < -1.0) yawValue = -1.0; 
  410.                     break;
  411.                 case kNeed_YawCenter:
  412.                     yawValue = 0.0;
  413.                     break;
  414.                 case kNeed_YawRight:
  415.                     yawValue += 0.1;
  416.                     if (yawValue > 1.0) yawValue = 1.0; 
  417.                     break;
  418.             }
  419.         }
  420.     }
  421.     while (wasEvent && !error);
  422.     
  423.     gYawValue = yawValue;
  424.     
  425.     return yawValue;
  426. }
  427.  
  428. float Input_GetThrottle (void)
  429. {
  430.     static    float        gThrottleValue = 0.0;
  431.     static    Boolean        gThrottleInitialized = false;
  432.     
  433.     float                throttleValue = gThrottleValue;
  434.     OSStatus            error = noErr;
  435.     ISpAxisData            axisValue;
  436.     Boolean                wasEvent;
  437.     ISpElementEvent        event;
  438.     
  439.     // should probably put the initialization check somewhere else, so does not do it every time
  440.     if (!gThrottleInitialized)
  441.     {
  442.         (void) ISpElement_GetSimpleState(gInputElement[kNeed_Throttle], &axisValue);
  443.         gThrottleValue = ISpAsymmetricAxisToFloat (axisValue);
  444.  
  445.         gThrottleInitialized = true;
  446.     }
  447.     
  448.     // we check the axis, to see if IT was moved, if so, we use that value
  449.     wasEvent = false;
  450.     error = ISpElement_GetNextEvent (gInputElement[kNeed_Throttle], sizeof (event), &event, &wasEvent);
  451.     if (!error && wasEvent)
  452.     {
  453.         error = ISpElement_GetSimpleState(gInputElement[kNeed_Throttle], &axisValue);
  454.         if (!error) throttleValue = ISpAsymmetricAxisToFloat (axisValue);
  455.  
  456.         ISpElement_Flush(gInputElement[kNeed_Throttle]);
  457.     }
  458.     else do
  459.     {
  460.         error = ISpElementList_GetNextEvent (gInputThrottleEventList, sizeof (event), &event, &wasEvent);
  461.         
  462.         // only process valid keydown events (all the throttle events ignore button ups)
  463.         if (wasEvent && !error && (event.data == kISpButtonDown))
  464.         {
  465.             UInt32 keyFunction = event.refCon; // because we set it this way
  466.             switch (keyFunction)
  467.             {
  468.                 case kNeed_ThrottleUp:
  469.                     throttleValue += 0.05;
  470.                     if (throttleValue > 1.0) throttleValue = 1.0; 
  471.                     break;
  472.                 case kNeed_ThrottleDown:
  473.                     throttleValue -= 0.05;
  474.                     if (throttleValue < 0.0) throttleValue = 0.0; 
  475.                     break;
  476.                 case kNeed_ThrottleFull:
  477.                     throttleValue = 1.0;
  478.                     break;
  479.                 case kNeed_ThrottleZero:
  480.                     throttleValue = 0.0;
  481.                     break;
  482.             }
  483.         }
  484.     }
  485.     while (wasEvent && !error);
  486.     
  487.     gThrottleValue = throttleValue;
  488.     
  489.     return throttleValue;
  490. }
  491.  
  492.  
  493.  
  494. /* =============================================================================
  495.  *        Input_GetEvent (external)
  496.  *
  497.  *    This routine handles the elements that are event-based.  It returns an
  498.  *    event code indicating which button has gone down.  Note that we ignore
  499.  *    button-up transitions.  Should be called repeatedly until it return
  500.  *    kInputEvent_None.
  501.  * ========================================================================== */
  502. TInputEvent Input_GetEvent(
  503.     void)
  504. {
  505.     OSErr                err;
  506.     TInputEvent            result = kInputEvent_None;
  507.     ISpElementEvent        event;
  508.     Boolean                gotEvent;
  509.     
  510.     if (gInputActive)
  511.     {
  512.         err = ISpElementList_GetNextEvent(gInputHoldDownEventList, sizeof(event), &event, &gotEvent);
  513.         if (err == noErr && gotEvent)
  514.         {
  515.             result = (TInputEvent) event.refCon;
  516.             if (event.data == kISpButtonUp)
  517.                 result += 1;    // Note: we rely on off being on+1 (ie kInputEvent_InertialDampers_Off == kInputEvent_InertialDampers_On + 1)
  518.         }
  519.         else
  520.         {
  521.             err = ISpElementList_GetNextEvent(gInputEventList, sizeof(event), &event, &gotEvent);
  522.             
  523.             if (err == noErr && gotEvent && event.data == kISpButtonDown)
  524.                 result = (TInputEvent) event.refCon;
  525.         }
  526.     }
  527.     
  528.     return result;
  529. }
  530.  
  531.  
  532. /* =============================================================================
  533.  *        Input_Activate (external)
  534.  *
  535.  *    On deactivation, we suspend InputSprocket.  On activation we resume it and
  536.  *    flush the event queue.  We only allow activation when the game is in "Play"
  537.  *    state.
  538.  * ========================================================================== */
  539. void Input_Activate(
  540.     Boolean                inActivate)
  541. {
  542.     Boolean                doActivate;
  543.     
  544.     doActivate = inActivate;
  545.     if (doActivate && Game_GetState() != kGameState_Playing)
  546.     {
  547.         doActivate = false;
  548.     }
  549.     
  550.     if (gInputActive != doActivate)
  551.     {
  552.         gInputActive = doActivate;
  553.         
  554.          if (gInputActive)
  555.          {
  556.              #if USE_MOUSE_AND_KEYBOARD
  557.                  HideCursor();
  558.              #endif
  559.              
  560.              ISpResume();
  561.              ISpElementList_Flush(gInputEventList);
  562.          }
  563.          else
  564.          {
  565.              ISpSuspend();
  566.              
  567.              #if USE_MOUSE_AND_KEYBOARD
  568.                  ShowCursor();
  569.              #endif
  570.          }
  571.     }
  572. }
  573.  
  574.  
  575.